/*
pcase.cpp : Defines the entry point for the application.
*/

#include <wave.h>

extern "C"{
#include <form.h>
}

#define	WAVE_SCALE  50

static TCHAR	wclass[]="WAVE";

static void DrawWave(HDC dc,BEAM *form,RECT *rect){
    U32	t,v,vo,*vs,*vx,x0,x1,xb,xx,y0,y1;

    y1=rect->top;
    y0=y1+24;
    x0=rect->left;
    xb=vo=t=0;
    xx=rect->right;
    MoveToEx(dc,x0,y0,NULL);
    for(vs=form->form,vx=vs+countof(form->form);(vs<vx)&&(v=*vs);vs++){
	t+=v&CNT_MASK;
	x1=rect->left+t/WAVE_SCALE-xb;
	if(v&~CNT_MASK){
	    LineTo(dc,x0,y1);
	    LineTo(dc,x1,y1);
	    LineTo(dc,x1,y0);
	    vo=1;
	}
	else{
	    if(!vo){
		LineTo(dc,x0,y1);
		LineTo(dc,x0,y0);
	    }
	    LineTo(dc,x1,y0);
	    vo=0;
	}
	if(x1>xx){
	    xb+=x1-rect->left;
	    x0=rect->left;
	    y0+=80;
	    y1+=80;
	    MoveToEx(dc,x0,y0,NULL);
	}
	else x0=x1;
    }
}

static void DrawForm(HDC dc,BEAM *beam,RECT *rect){
    U32	m,t,v,vo,x0,x1,xb,xx,y0,y1;
    U16	*vs,*vx;

    y1=rect->top;
    y0=y1+24;
    x0=rect->left+beam->timeout*500/WAVE_SCALE;
    MoveToEx(dc,x0,y0,NULL);
    LineTo(dc,x0,y1);

    m=beam->period*beam->repetition;
    x0=rect->left;
    xb=vo=t=0;
    xx=rect->right;
    MoveToEx(dc,x0,y0,NULL);
    for(vs=beam->wave+2,vx=vs+beam->head-2;vs<vx;vs++){
	t+=m;
	x1=rect->left+t/(WAVE_SCALE<<SLOT_SHIFT)-xb;
	if(v=*vs){
	    if(!vo)
		LineTo(dc,x0,y1);
	    LineTo(dc,x1,y1);
	}
	else{
	    if(vo)
		LineTo(dc,x0,y0);
	    LineTo(dc,x1,y0);
	}
	if(x1>xx){
	    xb+=x1-rect->left;
	    x0=rect->left;
	    y0+=80;
	    y1+=80;
	    MoveToEx(dc,x0,y0,NULL);
	}
	else x0=x1;
	vo=v;
    }
}


static LRESULT WmPaint(HWND hwnd,WPARAM wparam,LPARAM lparam){
    HDC		dc;
    PAINTSTRUCT ps;
    RECT	rc;
    HPEN	op;
    KEY		ky;
    TCHAR	s[300];
    BEAM	wv;
    SLOT	so[SLOT_LEN];

    FillMemory(&form,28,0);
    Fact(&form,so);
    dc=BeginPaint(hwnd,&ps);
    GetClientRect(hwnd,&rc);
    wsprintf(s,"%d, %d, %d, %d, %d-%d-%d-%d-%d-%d  %d-%d-%d-%d-%d-%d",
	form.period,form.repetition,form.head1,form.head0,
	so[2].fact,so[3].fact,so[4].fact,so[5].fact,so[6].fact,so[7].fact,
	so[8].fact,so[9].fact,so[10].fact,so[11].fact,so[12].fact,so[13].fact);
    TextOut(dc,32,2,s,strlen(s));
    InflateRect(&rc,-32,-120);
    DrawWave(dc,&form,&rc);
    if(Decode(&form,&ky,so)){
	wsprintf(s,"%d: %x%x",ky.vendor,ky.data2,ky.data1);
	TextOut(dc,32,22,s,strlen(s));
	wsprintf(s,"pr:%d, re:%d, hd:%d.%d, mx:%d.%d, bt:%d",form.period,form.repetition,
	    form.head1,form.head0,form.max0,form.max1,form.bits);
	TextOut(dc,32,42,s,strlen(s));
	wv=form;
	wv.pulse=1;
	Encode(&wv,&ky);
	op=(HPEN)SelectObject(dc,redpen);
	OffsetRect(&rc,1,28);
	DrawForm(dc,&wv,&rc);
	SelectObject(dc,op);
    }
    EndPaint(hwnd,&ps);
    return 0;
}

static LRESULT WmSize(HWND hwnd,WPARAM wparam,LPARAM lparam){
    return 0;
}

static LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wparam,LPARAM lparam){
    switch(message){
    case WM_PAINT:
	return WmPaint(hwnd,wparam,lparam);
    case WM_SIZE:
	return WmSize(hwnd,wparam,lparam);
    case WM_USER:
	InvalidateRect(hwnd,NULL,TRUE);
	break;
    default:
	return DefWindowProc(hwnd,message,wparam,lparam);
    }
    return 0;
}

//-----------------------------------------------------------------------------

HWND CreateWave(HINSTANCE hinst,HWND hframe,U32 id){
    return CreateWindowEx(WS_EX_CLIENTEDGE,wclass,NULL,WS_CHILD|WS_BORDER,
	0,0,0,0,hframe,(HMENU)id,hinst,NULL);
}

ATOM InitWave(HINSTANCE hins){
    WNDCLASS	c;

    c.style		=CS_HREDRAW|CS_VREDRAW;
    c.lpfnWndProc	=(WNDPROC)WndProc;
    c.cbClsExtra	=0;
    c.cbWndExtra	=0;
    c.hInstance		=hins;
    c.hIcon		=NULL;
    c.hCursor		=defcursor;
    c.hbrBackground	=(HBRUSH)(COLOR_WINDOW+1);
    c.lpszMenuName	=NULL;
    c.lpszClassName	=wclass;
    return RegisterClass(&c);
}
